package recite.word.client.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import recite.word.client.dto.user.GetUserDayDTO;
import recite.word.client.service.IPlanService;
import recite.word.client.service.IUserService;
import recite.word.client.vo.plan.CalendarData;
import recite.word.client.vo.user.DayWordList;
import recite.word.client.vo.user.GetPunchVO;
import recite.word.client.vo.user.GetUserDayVO;
import recite.word.client.vo.user.GetUserInfoVO;
import recite.word.mybatis.auto.dao.CalendarRecordMapper;
import recite.word.mybatis.auto.dao.PunchMapper;
import recite.word.mybatis.auto.dao.UserMapper;
import recite.word.mybatis.auto.dao.UserWordMapper;
import recite.word.mybatis.auto.model.CalendarRecord;
import recite.word.mybatis.auto.model.Punch;
import recite.word.mybatis.auto.model.User;
import recite.word.mybatis.auto.model.UserWord;
import recite.word.service.base.common.enums.DayCompleteEnum;
import recite.word.service.base.common.enums.DeleteEnum;
import recite.word.service.base.common.enums.MonthEnum;
import recite.word.service.base.common.enums.WeekEnum;
import recite.word.service.base.common.request.BaseRequest;
import recite.word.service.base.common.threadLocal.UserContent;
import recite.word.service.base.util.common.Asserts;
import recite.word.service.base.util.date.DateFormat;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private IPlanService planService;
    @Resource
    private PunchMapper punchMapper;
    @Resource
    private CalendarRecordMapper calendarRecordMapper;
    @Resource
    private UserWordMapper userWordMapper;

    /**
     * 获取打卡数据
     * @return
     */
    @Override
    public GetPunchVO getPunch() {
        Long userId = UserContent.get();
        User user = this.getById(userId);
        Calendar calendar = Calendar.getInstance();
        StringBuilder date = new StringBuilder();
        // 设置日期时间为 January, Monday 9 格式
        WeekEnum week = WeekEnum.getByType(calendar.get(Calendar.DAY_OF_WEEK));
        MonthEnum month = MonthEnum.getByType(calendar.get(Calendar.MONTH));
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        date.append(month).append(", ").append(week).append(" ").append(day);
        // 今日学习单词数
        Integer dayWord = planService.getTodayStudyNum();
        // 打卡图片url, 找到是否有当天时间的卡,如果有就用;没有就把最远时间的卡设置为当天
        List<Punch> punches = punchMapper.selectList(new LambdaQueryWrapper<Punch>()
                .select(Punch::getId,Punch::getUrl,Punch::getUseTime)
                .eq(Punch::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode())
                .orderByDesc(Punch::getUseTime));
        Asserts.isTrue(CollUtil.isNotEmpty(punches),"卡片不存在");
        String url = ""; // 封面图片url
        LocalDateTime oneUseTime = punches.get(0).getUseTime();
        LocalDateTime todayDate = LocalDateTime.now();
        int todayYear = todayDate.getYear();
        int todayMonth = todayDate.getMonthValue();
        int todayDay = todayDate.getDayOfMonth();
        // 没有当天的卡, 将最远的卡的时间设置成当天; 有就直接用
        if (todayYear != oneUseTime.getYear() || todayMonth != oneUseTime.getMonthValue() || todayDay != oneUseTime.getDayOfMonth()) {
            Punch punch = punches.get(punches.size() - 1);
            punch.setUseTime(todayDate);
            int b = punchMapper.updateById(punch);
            Asserts.isTrue(b == 1,"设置卡片日期失败");
            url = punch.getUrl();
        } else {
            url = punches.get(0).getUrl();
        }
        // 填充返回值
        GetPunchVO ans = new GetPunchVO();
        ans.setDate(date.toString());
        ans.setHead(user.getHeadUrl());
        ans.setDayWord(dayWord);
        ans.setName(user.getName());
        ans.setPersist(user.getInsistDayNum());
        ans.setUrl(url);
        return ans;
    }

    /**
     * 获取个人信息
     * @return
     */
    @Override
    public GetUserInfoVO getInfo() {
        Long userId = UserContent.get();
        User user = this.getById(userId);
        GetUserInfoVO ans = new GetUserInfoVO();
        ans.setDesc(user.getDesc());
        ans.setPersistDay(user.getInsistDayNum());
        ans.setStudyWord(user.getStudyWordNum());
        ans.setHead(user.getHeadUrl());
        ans.setName(user.getName());
        ans.setUrl(user.getCoverUrl());
        return ans;
    }

    /**
     * 获取某日打卡信息
     * @return
     */
    @Override
    public GetUserDayVO getDayInfo(BaseRequest<GetUserDayDTO> dto) {
        GetUserDayDTO data = dto.getData();
        Long userId = UserContent.get();
        CalendarRecord calendarRecord = calendarRecordMapper.selectOne(new LambdaQueryWrapper<CalendarRecord>()
                .eq(CalendarRecord::getUserId, userId)
                .eq(CalendarRecord::getCompleteDate,data.getDate())
                .eq(CalendarRecord::getDeleteStatus,DeleteEnum.NOT_DELETED.getCode()));
        GetUserDayVO ans = new GetUserDayVO();
        ans.setDate(data.getDate());
        if (ObjectUtil.isNull(calendarRecord)){
            ans.setComplete(DayCompleteEnum.NO_COMPLETE.getType());
            return ans;
        }
        ans.setComplete(DayCompleteEnum.COMPLETE.getType());
        // 用户当天学习单词,默认3个
        List<UserWord> words = userWordMapper.selectList(new LambdaQueryWrapper<UserWord>()
                .eq(UserWord::getUserId, userId)
                .eq(UserWord::getReciteDate, data.getDate())
                .eq(UserWord::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode())
                .orderByDesc(UserWord::getEditTime)
                .last("limit 3"));
        List<DayWordList> wordList = new ArrayList<>();
        for (UserWord word : words) {
            DayWordList dayWord = new DayWordList();
            dayWord.setWord(word.getWord());
            dayWord.setMeanCn(word.getMeanCn());
            wordList.add(dayWord);
        }
        ans.setDayWordLists(wordList);
        return ans;
    }

    /**
     * 获取连续打卡天数
     * @return
     */
    @Override
    public Integer getPunchContinue() {
        Long userId = UserContent.get();
        LambdaQueryWrapper<CalendarRecord> wrapper = new LambdaQueryWrapper<CalendarRecord>()
                .select(CalendarRecord::getCompleteDate,CalendarRecord::getCreatedTime)
                .eq(CalendarRecord::getUserId, userId)
                .eq(CalendarRecord::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode())
                .orderByDesc(CalendarRecord::getCreatedTime);
        List<CalendarRecord> calendarDay = calendarRecordMapper.selectList(wrapper);
        int continuesDay = 0;
        Calendar toDay = Calendar.getInstance();
        for (CalendarRecord record : calendarDay) {
            if (!DateFormat.format(toDay.getTime()).equals(record.getCompleteDate())) break;
            toDay.add(Calendar.DATE,-1);
            continuesDay ++;
        }
        return continuesDay;
    }

    /**
     * 获取当月打卡日期
     * @return
     */
    @Override
    public List<CalendarData> getPunchMonth() {
        String nowMonth = DateFormat.format2month(new Date());
        LambdaQueryWrapper<CalendarRecord> wrapper = new LambdaQueryWrapper<CalendarRecord>()
                .select(CalendarRecord::getCompleteDate,CalendarRecord::getCreatedTime)
                .eq(CalendarRecord::getUserId, UserContent.get())
                .eq(CalendarRecord::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode())
                .orderByDesc(CalendarRecord::getCreatedTime)
                .eq(CalendarRecord::getCompleteDateMonth,nowMonth);
        return calendarRecordMapper.selectList(wrapper)
                .stream()
                .map(item -> new CalendarData(item.getCompleteDate())).collect(Collectors.toList());
    }


}
